package org.rcy.framework.storage;

import org.rcy.framework.api.storage.StorageService;
import org.rcy.framework.api.storage.StorageStrategy;
import org.springframework.beans.factory.annotation.Autowired;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

/**
 * @author 吴康桥
 * @Description
 * @date 2023/7/4 11:02
 */


public class StorageServiceImpl implements StorageService {

	private List<StorageStrategy> storageStrategies;

	public StorageServiceImpl(List<StorageStrategy> storageStrategies) {
		this.storageStrategies = storageStrategies;
	}

	@Override
	public String uploadFile(byte[] bytes) {
		ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
		for (StorageStrategy storageStrategy : storageStrategies) {
			String fileKey = storageStrategy.uploadFile(inputStream, bytes.length);
			if(fileKey != null) {
				return fileKey;
			}
		}
		return null;
	}

	@Override
	public String uploadFile(File file) throws Exception {
		FileInputStream fis = new FileInputStream(file);
		for (StorageStrategy storageStrategy : storageStrategies) {
			String fileKey = storageStrategy.uploadFile(fis, file.length());
			if(fileKey != null) {
				return fileKey;
			}
		}
		return null;
	}

	@Override
	public String uploadFile(byte[] bytes, String secretKey) throws Exception {
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(1, new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES"));
		byte[] enBtyes = cipher.doFinal(bytes);
		ByteArrayInputStream inputStream = new ByteArrayInputStream(enBtyes);
		for (StorageStrategy storageStrategy : storageStrategies) {
			String fileKey = storageStrategy.uploadFile(inputStream, enBtyes.length);
			if(fileKey != null) {
				return fileKey;
			}
		}
		return null;
	}

	@Override
	public void uploadFile(String fileKey, InputStream input, long size) throws Exception {
		for (StorageStrategy storageStrategy : storageStrategies) {
			if(storageStrategy.uploadPublicFile(input,fileKey,size)){
				return;
			}
		}
	}

	@Override
	public byte[] downloadFile(String fileKey) throws Exception{
		for (StorageStrategy storageStrategy : storageStrategies) {
			InputStream inputStream = storageStrategy.downloadFile(fileKey);
			byte[] bytes = downloadBytes(inputStream);
			if(bytes.length != 0) {
				return bytes;
			}
		}
		return null;
	}

	@Override
	public byte[] downloadFile(String fileKey, String secretKey) throws IOException {
		for (StorageStrategy storageStrategy : storageStrategies) {
			InputStream inputStream = storageStrategy.downloadFile(fileKey);
			byte[] bytes = downloadBytes(inputStream);
			if(bytes.length != 0) {
				return bytes;
			}
		}
		return null;
	}

	private byte[] downloadBytes(InputStream in) throws IOException {
		ByteArrayOutputStream tempStream = new ByteArrayOutputStream();
		byte[] buffer = new byte[8192];

		int r;
		while((r = in.read(buffer, 0, 8192)) != -1) {
			tempStream.write(buffer, 0, r);
		}

		return tempStream.toByteArray();
	}
}
